
const { SearchToken, Hotword, SensitiveWord } = require('../models/')
const BaseService = require('./msg_center')
const esClient = require('../db/elasticsearch')
const { Picture, App } = require('../config/constant')
const log = require('../libs/logger')
const utils = require('../libs/utils')

class SearchService extends BaseService {
  constructor () {
    super()
    this.indices = Picture.alias
    this.type = Picture.esType
  }
  // 搜索
  static async doSerach (options = {}) {
    // const indices = options.indices || [this.indices]
    const strIndices = Picture.alias
    let keyword = options.keyword

    if (!keyword || keyword.length === 0) {
      return { list: [], total: 0 }
    }

    const page = options.page || 1
    const pageSize = options.page_size || 20
    const offset = (page - 1) * pageSize

    const serarchOptions = {
      index: strIndices,
      type: this.type,
      _source: ['id', 'title', 'file_name', 'tags', 'publish_time', 'exif'],
      size: pageSize,
      from: offset,
      body: {
        'query': {
          'constant_score': {
            'filter': {
              'bool': {
                'should': [
                  { 'multi_match': {
                    'type': 'most_fields',
                    'query': keyword,
                    'fields': ['title'] }
                  },
                  { wildcard: { 'keyword_title': { 'value': '*' + keyword + '*' } } }
                ]
              }
            }
          }
        },
        'sort': [{ 'publish_time': { 'order': 'desc' } }]
      }
    }
    try {
      const tokens = await this.getTokens(strIndices, Picture.analyzer, keyword)
      // console.log({ tokens })
      const searchTokens = await SearchToken.getByNames(tokens)
      const searchTagIds = searchTokens.map((item) => item.id)
      // console.log({ searchTagIds })
      if (searchTagIds && searchTagIds.length > 0) {
        serarchOptions.body.query.constant_score.filter.bool.should.push({
          terms: { 'search_tag_ids': searchTagIds }
        })
      }
      // log.info(`${indices} doSearch optinos:`, JSON.stringify(serarchOptions))
      const res = await esClient.search(serarchOptions)
      // log.info(`${indices} doSearch optinos:`, JSON.stringify(serarchOptions), 'finished')
      const total = res.hits.total
      let list = res.hits.hits.map((item) => item._source)
      const relateKeywords = this._getRelatedKeywords(list, keyword)
      const search = {
        keyword: keyword,
        relate_keywords: relateKeywords
      }

      return { list, total, search }
    } catch (error) {
      log.error(error)
      return { list: [], total: 0 }
    }
  }

  // 补全提示词
  static async complete (options = {}) {
    let q = options.q
    const res = await SearchToken.getByPrefix(q)
    const list = res.map((item) => item.name)
    return { list }
  }

  static _getRelatedKeywords (list, keyword) {
    let tags = []
    list.map((item) => { tags = tags.concat(item.tags) })

    let map = {}
    let destList = []
    for (var i = 0; i < tags.length; i++) {
      var tag = tags[i]
      if (tag.name === keyword) { continue }
      if (!map[tag.id]) {
        destList.push({
          id: tag.id,
          name: tag.name,
          value: 1
        })
        map[tag.id] = tag
      } else {
        for (var j = 0; j < destList.length; j++) {
          var destObj = destList[j]
          if (destObj.id === tag.id) {
            ++destObj.value
            break
          }
        }
      }
    }

    destList = destList.sort((a, b) => b.value - a.value)
    const allRelatedKeyword = destList.map((item) => item.name)
    return allRelatedKeyword.slice(0, 10)
  }

  // 搜索
  static async hotword (options = {}) {
    let page = Math.round(Math.random()) + 1
    let res = await Hotword.getList({ app: App, status: 1, page, page_size: 10 })
    if (res.length === 0) {
      res = await Hotword.getList({ app: App, status: 1, page: 1, page_size: 10 })
    }
    return { list: res }
  }

  // 过滤敏感词
  static async filterKeyword (keyword) {
    const kid = utils.MD5(keyword)
    const res = await SensitiveWord.getByKid(kid)
    console.log(111111111, res, keyword)
    if (res && res[0]) {
      return ''
    } else {
      return keyword
    }
  }
}

module.exports = SearchService
